package com.powernode.controller;

import com.powernode.constant.Constants;
import com.powernode.entity.Goods;
import com.powernode.entity.Orders;
import com.powernode.entity.Users;
import com.powernode.service.LuaService;
import com.powernode.vo.HttpResult;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * 秒杀控制器，负责处理商品秒杀的核心业务逻辑
 * 采用REST风格API设计，通过Redis+Lua实现高并发下的库存控制
 */
@RestController
public class SeckillController {
    @Resource
    private RedisTemplate redisTemplate;  // Redis模板，用于操作Redis缓存

    @Resource
    private LuaService luaService;  // Lua脚本服务，用于执行原子性的秒杀逻辑

    @Resource
    private RabbitTemplate rabbitTemplate;  // RabbitMQ模板，用于发送订单消息

    @Resource
    private ObjectMapper objectMapper;  // JSON序列化工具，用于订单对象转JSON

    /**
     * 执行秒杀的核心接口
     * 实现步骤：
     * 1. 验证随机码有效性
     * 2. 检查秒杀时间窗口
     * 3. 执行Lua脚本进行原子性库存检查和扣减
     * 4. 处理秒杀结果并创建订单
     * 5. 将订单信息发送到RabbitMQ进行异步处理
     *
     * @param request HTTP请求对象
     * @param id 商品ID路径参数
     * @param random 秒杀随机码路径参数
     * @param userId 用户ID请求参数
     * @return 包含秒杀结果的HttpResult对象
     * @throws JsonProcessingException JSON序列化异常
     */
    @PostMapping("/goods/{id}/{random}")
    public HttpResult execSeckill(HttpServletRequest request, @PathVariable("id") Integer id,
                                  @PathVariable("random") String random, Integer userId) throws JsonProcessingException {
        // 从Redis中获取商品信息，Constants.REDIS_GOODS是商品缓存的key前缀
        Goods goods = (Goods) redisTemplate.opsForValue().get(Constants.REDIS_GOODS + id);

        // 验证随机码，防止秒杀接口被直接调用
        if (!goods.getRandomName().equals(random)) {
            return HttpResult.builder().code(Constants.ERROR).msg("随机码不合法").build();
        }

        // 获取当前时间和秒杀时间窗口，验证秒杀是否在有效期内
        long currentTime = System.currentTimeMillis();
        long startTime = goods.getStartTime().getTime();
        long endTime = goods.getEndTime().getTime();

        if (currentTime < startTime) {
            return HttpResult.builder().code(Constants.ERROR).msg("秒杀未开始").build();
        }

        if (currentTime > endTime) {
            return HttpResult.builder().code(Constants.ERROR).msg("秒杀已结束").build();
        }

        // 构建用户信息（实际项目中应从Session或Token中获取）
        Users user = (Users) request.getSession().getAttribute(Constants.LOGIN_USER);
        //Users user = Users.builder().id(userId).build();

        // 执行Lua脚本，实现原子性的库存检查和扣减
        // 返回值说明：
        // -1: 用户已秒杀过该商品
        // -2: 系统繁忙，未获取到库存锁
        // -3: 库存不足
        // 其他正数: 剩余库存
        long result = luaService.runLuaScript(id, user.getId() + "");

        if (result == -1) {
            return HttpResult.builder().code(Constants.ERROR).msg("用户秒杀过该商品").build();
        }

        if (result == -2) {
            return HttpResult.builder().code(Constants.ERROR).msg("服务器太拥挤，没有挤进去").build();
        }

        if (result == -3) {
            return HttpResult.builder().code(Constants.ERROR).msg("库存不足").build();
        }

        // 秒杀成功，创建订单对象
        Orders orders = Orders.builder()
                .orderMoney(goods.getPrice())  // 订单总金额
                .uid(user.getId())             // 用户ID
                .buyNum(1)                     // 购买数量（默认为1）
                .buyPrice(goods.getPrice())    // 商品单价
                .goodsId(goods.getId())        // 商品ID
                .createTime(new Date())        // 订单创建时间
                .status(0).build();            // 订单状态：0-未支付

        // 将订单对象序列化为JSON字符串
        String jsonOrder = objectMapper.writeValueAsString(orders);

        // 将订单JSON发送到RabbitMQ，使用订单交换机和路由键
        rabbitTemplate.convertAndSend(Constants.EXCHANGE_NAME_ORDER, Constants.ROUTING_KEY_ORDER,
                jsonOrder);

        // 返回秒杀结果，提示用户稍后查询结果
        return HttpResult.builder().code(Constants.SUCCESS)
                .msg("秒杀中，请稍后查看秒杀结果").data(result).build();
    }
}